home *** CD-ROM | disk | FTP | other *** search
- page 132,63,1,1
- opt rc
- title 'PAM Modulation/Demodulation'
-
- ;***************************************************************
- ;* PAM.ASM -- PAM Modulation/Demodulation and *
- ;* SSI drivers *
- ;* *
- ;* Provides interrupt based SSI handling, sample buffering *
- ;* and PAM modulation and demodulation. *
- ;* *
- ;* PAM modulation and demodulation is based on some ideas *
- ;* presented in book *
- ;* Lee, E., A., Messerschmitt, D., G.: *
- ;* "Digital Communication", *
- ;* Kluwer, 1988 *
- ;* *
- ;* Symbol syncronization is based on article *
- ;* Glisic, S., G.: *
- ;* "Symbol Syncronization in Digital Communications *
- ;* Using Partial Response CPM signaling", *
- ;* IEEE Trans. on Comm., Vol. 37, No. 3, March 1989 *
- ;* *
- ;* This module uses registers as follows: *
- ;* r0 - general purpose (temporary use) *
- ;* r2 - input sample write pointer *
- ;* r3 - output sample read pointer *
- ;* r4 - general purpose (temporary use) *
- ;* r6 - input sample read pointer *
- ;* r7 - output sample write pointer *
- ;* *
- ;* Copyright (C) 1991 by Alef Null. All rights reserved. *
- ;* Author(s): Jarkko Vuori, OH2LNS *
- ;* Modification(s): *
- ;***************************************************************
-
- nolist
- include 'ioequlc'
- list
-
- section PAM
- xdef ssi_ini,modem_i
- xdef m_loop
- xref putbit,getbit
- xref m_cra,m_crb,m_tde,m_sr,m_tx
-
- org p:
-
- nolist
- include 'macros'
- list
-
- ; PAM sync parameters
- poly equ $10010 ; G3RUH,K9NG scrambler polynomial (x^17 + x^12 + 1)
- cM0 equ 6 ; random walk filter constant
- adjlen equ 18 ; ADC timing control lenght (in samples)
- analen equ 32 ; sample quality analyzing lenght
-
- ; module status bits
- toggle equ 6 ; every other bit counter
-
- ; first order high-pass IIR filter
- ; input in a, output in a
- ; frq is -3dB point (fc/fs)
- hpass macro acc,frq,store
- c1 set -1.0/@cos(6.28319*frq)*(1.0-@sin(6.28319*frq))
- move acc,x0
- move #(1.0-c1)/2.0,x1
- mpyr x0,x1,acc x:<store,x1
- move acc,x:<store
- sub x1,acc x:<store+1,x0
- move #c1,x1
- macr -x0,x1,acc
- move acc,x:<store+1
- endm
-
- ; first order low-pass IIR filter
- ; input in a, output in a
- ; frq is -3dB point (fc/fs)
- lpass macro acc,frq,store
- c1 set -1.0/@cos(6.28319*frq)*(1.0-@sin(6.28319*frq))
- move acc,x0
- move #(1.0+c1)/2.0,x1
- mpyr x0,x1,acc x:<store,x1
- move acc,x:<store
- add x1,acc x:<store+1,x0
- move #c1,x1
- macr -x0,x1,acc
- move acc,x:<store+1
- endm
-
-
- ;****************************
- ;* SSI initialization *
- ;****************************
- ssi_ini
- ; initialize SSI,
- IF !DEBUG
- movep #$4000,x:m_cra ; 16 bit word
- movep #$f200,x:m_crb ; syncronous,word frame,ext clk
- ELSE
- movep #$4011,x:m_cra ; 16 bit word, abt. 19.2 ksamples/s
- movep #$f620,x:m_crb ; syncronous,word frame,ext clk
- ENDIF
-
- rts
-
-
- ;****************************
- ;* ADC & MODEM *
- ;* initialization *
- ;****************************
- modem_i
- ; program the A/D & D/A converter chip (TLC32044, master clock is 5.184MHz)
- ; disable A/D high-pass filter, disable loopback, disable AUX IN,
- ; select syncronous mode, select input span 3Vpp, insert sinx/x correction
- ; lowpass cutoff frequency at 6840Hz -> TA = 5 (SCF = 518.4kHz)
- ; sampling frequency is 19200Hz -> TB = 27
- ; unit sampling correction time 0.6uS -> TA' = 3
- pgmtlc %10101000,5,3,27
-
- ; sample handling,
- move #<insamp,r6
- move #<inN-N,n6
- move #<inN-1,m6
- move r6,r2
- move m6,m2
- movi 0,x:<samque
-
- move #<outsamp,r3
- move #<outN-1,m3
- move #<outsamp+1,r7
- move m3,m7
- movi <outfilt,x:<outfptr
-
- ; symbol syncro logic,
- movi cM0,x:<rwalk
- movi analen,x:<anacnt
- movi 0,x:<goodcnt
-
- ; ADC command word
- movi 0,x:<adcnt
-
- rts
-
-
- ;****************************
- ;* Main Loop *
- ;****************************
- loop wait
- m_loop
-
-
- ;****************************
- ;* Receiver *
- ;****************************
- ; check if there are new samples received
- rec move r2,a
- move r6,x0
- cmp x0,a #<rcos,r0
- jeq <xmit
-
- ; yes, there indeed are new samples, check if receiver enabled
- jset #ptt,x:<status,xmit
-
- ; receive squared raised cosine filter
- conv 1,N,r6,r0,a
-
- ; remove any DC-level (with high-pass filter)
- hpass a,40.0/19200.0,rdc
-
- ; limit to binary and queue received bits
- andi #$fe,ccr
- jmi <ssi_r00
- ori #$01,ccr
- ssi_r00 move x:<samque,b1
- rol b (r6)+n6
- move b1,x:<samque
-
- ; queue received samples
- move y:<pzsample,b1
- move b1,y:<pdsample
- move y:<dsample,b1
- move b1,y:<pzsample
- move y:<zsample,b1
- move b1,y:<dsample
- move a,y:<zsample
-
- ; check if one symbol (2 samples) received
- bchg #toggle,x:<status
- jcc <ssi_end
-
- ; check if carrier present
- ; by checking when eye is open
- ; (enought difference between zero crossing sample and decision sample)
- move y:<dsample,a ; filter decision samples
- abs a
- lpass a,40.0/19200.0,rds
-
- move y:<zsample,b ; filter zero crossing samples
- abs b
- lpass b,40.0/19200.0,rzs
-
- sub b,a #>2500,x0 ; check their difference
- cmpm x0,a
- jhs <ssi_r0a
-
- bclr #dcd,x:<status ; dcd off
- jcc <ssi_r0b
- dcdoff
- jsset #req,x:<status,kickx ; call persistence routine if needed
- jmp <ssi_r0b
- ssi_r0a bset #dcd,x:<status ; dcd on
- jcs <ssi_r0b
- dcdon
-
- ssi_r0b
- ; experimental symbol syncro
- move y:<dsample,a ; calculate decision difference
- tst a #-1.0,x0
- move #0.999999,a
- tmi x0,a
- move y:<pdsample,b
- tst b ; limit to -1.0 or 1.0
- move #0.999999,b
- tmi x0,b
- sub b,a
-
- move a,x1 ; calculate and smooth clock adjust term
- move y:<pzsample,x0
- mpy x0,x1,a
- lpass a,3.0/9600.0,rsym
-
- move #>8000,x0 ; if spesified threshold is
- cmpm x0,a ; met, adjust timing
- jlo <ssi_yyy
- tst a
- jpl <ssi_xxx
- movib retard,x:<adccmd
- movib adjlen,x:<adcnt
- jmp <ssi_yyy
- ssi_xxx movib advance,x:<adccmd
- movib adjlen,x:<adcnt
- jmp <ssi_yyy
-
- ssi_yyy swi
- jmp <ssi_r4
-
- ; check if there are transitions (by analyzing the sample between decision samples)
- ; (...X|*X|*X|*...)
- ; where X decision sample
- ; * analyzed sample
- ; | symbol boundaries
- move #>-1,x1
- clr a #>1,x0
- jclr #1,x:<samque,ssi_l1
- jset #3,x:<samque,ssi_le
- ; 0x1
- move x0,a
- btst #2,x:<samque
- tcc x1,a
- jmp <ssi_le
- ssi_l1 jclr #3,x:<samque,ssi_le
- ; 1x0
- move x1,a
- btst #2,x:<samque
- tcc x0,a
-
- ; symbol syncro
- ssi_le tst a x:<rwalk,x0
- jeq <ssi_r4
- add x0,a #>2*cM0,x0
- jpl <ssi_r2
- ; retard sampling
- move #cM0,a1
- movib retard,x:<adccmd
- movib adjlen,x:<adcnt
- jmp <ssi_r3
- ;
- ssi_r2 cmp x0,a
- jle <ssi_r3
- ; advance sampling
- move #cM0,a1
- movib advance,x:<adccmd
- movib adjlen,x:<adcnt
- ;
- ssi_r3 move a1,x:<rwalk
-
- ; unscramble symbol, result in C
- ssi_r4 btst #1,x:<samque
- move x:<usrem,b1
- jcc <unscram
- move #>(poly<<1)|1,x0
- eor x0,b
- unscram lsr b
- move b1,x:<usrem
-
- ; make symbol decision (with NRZ-S decoding), databit in C, result in C
- rol b x:<prvrsym,x0
- eor x0,b b1,x:<prvrsym
- not b
- lsr b
-
- ; forward to the HDLC handler
- jsr <putbit
-
- ssi_end jmp <rec
-
-
- ;****************************
- ;* Transmitter *
- ;****************************
- ; check if we can calculate new samples
- xmit move r3,a
- move r7,x0
- cmp x0,a
- jeq <loop
-
- ; yes, check if the transmitter is on at all
- clr a
- jclr #ptt,x:<status,xmt2
-
- ; xmit mode, check if we need a new symbol
- bchg #toggle,x:<status
- jcc <xmt1
-
- ; yes, check on what phase we are
- jset #xmt,x:<status,xmt0
-
- ; training phase, send continuous preamble (zero pattern)
- andi #$fe,ccr
- jmp <morebit
-
- ; data phase, get a new bit to xmit
- xmt0 jsr <getbit
- jne <morebit
- ; there is no more bits to send, switch to receiving mode
- jsr <shutx
- jmp <scx_end
-
- ; NRZ-S coding
- morebit rol a x:<prvxsym,x0
- not a
- eor x0,a #-1.0,x0
- ror a a1,x:<prvxsym
-
- ; scrambler, databit in C flag, result in a (-1 or 1)
- clr a
- rol a x:<srem,x0
- eor x0,a #-0.9,x1
- lsr a #>poly,x0
- jcc <scram
- eor x0,a
- scram move a1,x:<srem
- move #0.9,a
- tcc x1,a
-
- ; squared raised cosine shape output filter
- xmt1 move x:<outfptr,r4
- move #<rcos,r0
- move #<N-1,m4
- move a,x:(r4)
- conv 1,N,r4,r0,a
- move r4,x:<outfptr
- move #-1,m4
-
- ; send a new bit
- move a,x0 ; adjust output level
- move x:<gain,x1
- mpyr x0,x1,a #>$fffc<<8,x0
- xmt2 and x0,a x:<adcnt,b
- tst b #>1,y0 ; check if we must adjust timing
- jeq <xmt3
- sub y0,b x:<adccmd,x0 ; yes, add converter chip control cmds
- or x0,a b1,x:<adcnt
- xmt3 move a,x:(r7)+
-
- scx_end jmp <xmit
-
-
- ;****************************
- ;* DATA - AREA *
- ;****************************
-
- org x:
-
- adccmd ds 1 ; ADC timing command
- adcnt ds 1 ; ADC timing command counter
- samque ds 1 ; received sample queue
- prvrsym ds 1 ; previous received symbol
- prvxsym ds 1 ; previous xmitted symbol
- rwalk ds 1 ; random walk filter counter
- rds ds 2 ; runnning average
- rzs ds 2 ; runnning average
- rdc ds 2 ; DC-level filter
- rsym ds 2
- anacnt ds 1 ; signal quality analyzing lenght counter
- goodcnt ds 1 ; good symbol counter
- usrem ds 1
- srem ds 1
- outfptr ds 1 ; output filter pointer
-
- tmp ds 1
-
-
- org y:
-
- zsample ds 1 ; current zero crossing sample
- dsample ds 1 ; previous decision sample
- pzsample ds 1 ; current zero crossing sample
- pdsample ds 1 ; previous decision sample
-
- endsec
-
-
- ;****************************
- ;* M*BITS MODULO DATA *
- ;****************************
- section PAMData
- xdef N,inN,outN,rcos
- xdef insamp,outsamp,outfilt
-
- org x:
-
- ; PAM demod parameters
- N equ 13 ; samples per filter
- inN equ 16 ; input buffer lenght
- outN equ 8 ; output buffer lenght
-
- insamp ds inN
- outfilt ds N
- ds 16-N
- outsamp ds 8
-
- org y:
-
- ; square root of raised cosine pulse filter constants
- ; beta = 6/16 = 0.375
- rcos dc -0.0082167989
- dc 0.0071048900
- dc 0.0254175599
- dc -0.0592829199
- dc -0.0434475299
- dc 0.2999202999
- dc 0.5512325000
- dc 0.2999202999
- dc -0.0434475299
- dc -0.0592829199
- dc 0.0254175599
- dc 0.0071048900
- dc -0.0082167989
-
- endsec
-
- end
-